﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MethodWorx.Core.DomainModel
{
    [Serializable]
    public class ChildEntityCollection<TParent, T> : IEnumerable<T> where T: Entity
    {
        private Func<TParent, IEnumerable<T>> loader;
        private TParent parent;
        protected IList<T> children;

        /// <summary>
        /// Construct the child entity collection passing in the loader delegate
        /// </summary>
        /// <param name="loader"></param>
        public ChildEntityCollection(TParent parent, Func<TParent, IEnumerable<T>> loader)
        {
            if(parent == null)
                throw new ArgumentNullException("parent");

            if(loader == null)
                throw new ArgumentNullException("loader");

            this.loader = loader;
            this.parent = parent;
        }

        protected virtual void LoadCollection()
        {
            //  load the collection
            this.children = this.loader(parent).ToList();
        }

        public bool IsLoaded
        {
            get { return this.children != null; }
        }
    
        public IEnumerator<T>  GetEnumerator()
        {
 	        if(this.children == null)
                this.LoadCollection();

            return this.children.GetEnumerator();
        }

        System.Collections.IEnumerator  System.Collections.IEnumerable.GetEnumerator()
        {
 	        if(this.children == null)
                this.LoadCollection();

            return this.children.GetEnumerator();
        }

        protected void Clear()
        {
            if (this.children == null)
                this.LoadCollection();

            this.children.Clear();
        }

        public void Refresh()
        {
            this.children = null;
        }

        public TParent Parent
        {
            get { return this.parent; }
        }

        protected void Add(T item)
        {
            if (this.children == null)
                this.LoadCollection();

            this.children.Add(item);
        }

        protected void Remove(T item)
        {
            if (this.children == null)
                this.LoadCollection();

            this.children.Remove(item);
        }

        public T this[Guid id]
        {
            get
            {
                if (this.children == null)
                    this.LoadCollection();

                return this.children.FirstOrDefault(c => c.Id == id);
            }
        }
    }
}
